<?php
//$Id: Cos.php 40 2009-04-02 14:56:47Z vipzhicheng $

/**
 * CosPHP 核心类, 出于使用上的便利和本类的扩展用法，请使用本类的继承类开发程序
 *
 * 本类库依赖于将类库所在文件夹加入include_path
 *
 * @link http://cosphp.com/
 * @Copyright (c) 2008-2009 CosPHP Inc. {@link http://www.cosphp.com}
 * @license New BSD License {@link http://cosphp.com/license/}
 * @version $Id: Cos.php 40 2009-04-02 14:56:47Z vipzhicheng $
 * @package core
 */

class Cos
{
    const ID = '$Id: Cos.php 40 2009-04-02 14:56:47Z vipzhicheng $';

    protected static $_path       = array();
    protected static $_objects    = array();

    
    private function __construct() {}

    /**
     * 自动回收模式实例化
     *
     * @return object 对象
     */
    public final static function getObject($className)
    {
        $args = func_get_args();
        unset($args[0]);
        if (class_exists($className)) {
            foreach ($args as $arg)
            {
                if (is_bool($arg)) {
                    if ($arg == true) {
                        $arg = 'true';
                    } else {
                        $arg = 'false';
                    }
                } elseif (is_array($arg)) {
                    $arg = var_export($arg, true);
                } elseif (is_numeric($arg)) {
                    //nothing to do
                } elseif (is_string($arg)) {
                    $arg = '\'' . $arg . '\'';
                } elseif (is_object($arg)) {
                    $arg = 'unserialize(\'' . serialize($arg) .'\')';
                }
                $argstr .= is_null($argstr) ? $arg : ', ' . $arg;
            }

            eval('$GLOBALS[_] = new ' . $className . '(' . $argstr . ');');
            return $GLOBALS[_];
        } else {
            throw new Exception('The Class is not exist!');
        }
    }
    /**
     * 单例模式实例化,特点是可以在实例化时传入参数
     *
     * @return object 对象
     */
    public final static function getSingleton($className)
    {
        $args = func_get_args();
        unset($args[0]);
        if (isset(self::$_objects[$className])) {
            return self::$_objects[$className];
        } else {
            $obj = call_user_func_array(array('Cos', 'getObject'), $args);
            self::$_objects[$className] = $obj;
            return $obj;
        }
    }


    /**
     * 设置include_path路径
     *
     * 因为这个方法不常用，所以参数形式十分简单
     *
     * @param mixed $path 路径
     * @return mixed
     */
    public final static function setIncludePath($path)
    {
        $args = func_get_args();
        foreach ($args as $path)
        {
            $path = realpath($path);
            if (isset(self::$_path[$path])) return;
            if (is_dir($path)) {
                set_include_path($path . PATH_SEPARATOR . get_include_path());
                self::$_path[$path] = $path;
            } else {
                throw new Exception($path . ' is not exist!');
            }
        }
    }

    /**
     * 载入文件
     *
     * $dir 的格式如下
     * 1，可以是字符串
     * 2，可以是数组，每一项都是字符串
     * 3，如果为空意思是只在上文设定的include_path中查找
     *
     * 参考Zend Framework
     *
     * @param <string> $filePath 真实路径，相对于include_path
     * @param mixed $path 路径，与addPath的区别是先设置的路径优先级更高
     */
    public static function loadFile($filePath, $dir = null, $once = false)
    {
        $incPath = false;
        if (!empty($dir) && (is_array($dir) || is_string($dir))) {
            if (is_array($dir)) {
                $dir = array_reverse($dir);
                $dir = implode(PATH_SEPARATOR, $dir);
            }
            $incPath = get_include_path();
            set_include_path($dir . PATH_SEPARATOR . $incPath);
        }

        $ifexist = false;
        $allSearchPath = explode(PATH_SEPARATOR, get_include_path());
        foreach ($allSearchPath as $value) {
            if (is_file($value . '/' . $filePath)) {
                $ifexist = true;
                break;
            }
        }
        
        if(!$ifexist) {
            return false;
        }

        if ($once) {
            $return = include_once $filePath;
        } else {
            $return = include $filePath;
        }

        if ($incPath) {
            set_include_path($incPath);
        }

        return $return;
    }

    /**
     * 载入COS类文件
     *
     * @param <type> $classPath 类路径，例如cos.exception
     */
    public static function import($classRoute, $dir = null, $once = true)
    {
        $classRoute = strtolower($classRoute);
        $parts = explode('.', $classRoute);
        foreach ($parts as $key => $part) {
            $parts[$key] = ucfirst($part);
        }

        $filePath = implode(DIRECTORY_SEPARATOR, $parts) . '.php';
        return self::loadFile($filePath, $dir, $once);
    }

    /**
     * 类自动载入,只能自动载入COS的类
     *
     * @param string $class_name
     */
    protected static function autoload($className)
    {
        $parts = array();
        $pattern = '/[A-Z][a-z0-9]*/';
        preg_match_all($pattern, $className, $parts);
        if (!empty($parts[0]))
        {
            self::import(implode('.', $parts[0]));
        }
        
    }

    /**
     * 注册或取消注册一个自动类载入方法
     *
     * 该方法参考 Zend Framework。
     *
     * @param string $class 提供自动载入服务的类
     * @param boolean $enabled 启用或禁用该服务
     */
    public final static function registerAutoload($callback)
    {
        if (!function_exists('spl_autoload_register')) {
            throw new Exception('SPL is not installed!');
        }

        spl_autoload_register($callback);

    }
}
Cos::setIncludePath(realpath(dirname(__FILE__)) . '/Libs');
Cos::registerAutoload(array('Cos', 'autoload'));

